use crate::config::app_config::CONFIG;
use crate::config::handler_config::catcher_error;
use crate::config::log_config::config_tracing_log;

use config::db_config::DbConfig;
use config::handler_config::handler_auth;
use config::router_config::MyRouter;
use mimalloc::MiMalloc;
use salvo::catcher::Catcher;
use salvo::cors::Cors;

use salvo::prelude::{Logger, StaticDir};

use salvo::server::ServerHandle;

use salvo::{conn::TcpListener, Listener, Router, Server, Service};

use sqlx::Sqlite;

use crate::control::login_control::{login, logout, user_tree_menu};
use crate::control::menu_control::{add_menu, del_menu};
use crate::control::org_control::{add_org, org_page};
use crate::control::role_control::{add_role, del_role};
use crate::control::user_control::{add_user, del_user, user_page};
use crate::control::wx_callback_control::wx_call_back;
use crate::wechat::control::wechat_controller::{cursor, page};
use std::path::MAIN_SEPARATOR;
use std::sync::OnceLock;

mod config;
mod control;
mod entity;
mod service;
mod util;
mod vo;
mod wcferry;
mod wechat;

pub static SQLX: OnceLock<sqlx::Pool<Sqlite>> = OnceLock::new();
pub static WCFERRY: OnceLock<wcferry::WeChat> = OnceLock::new();

#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;

#[tokio::main]
pub async fn main() -> anyhow::Result<()> {
    let (_work_guard_1, _work_guard_2) = config_tracing_log()?;
    let sqlx_pool = DbConfig::sqlx_pool().await?;
    SQLX.get_or_init(|| sqlx_pool);

    // let wcferry = wcferry::WeChat::new(true, "http://localhost:4200/wx_call_back".into())?;
    //
    // WCFERRY.get_or_init(|| { wcferry });

    let http_addr = &CONFIG.server.http;
    let acceptor = TcpListener::new(http_addr).bind().await;
    let router = MyRouter::route()?;

    let service = Service::new(router)
        .hoop(Logger::new())
        .catcher(Catcher::default().hoop(catcher_error));
    let handler = Server::new(acceptor);
    let handle = handler.handle();
    tokio::spawn(stop_server(handle));
    handler.serve(service).await;
    Ok(())
}

async fn stop_server(handle: ServerHandle) -> anyhow::Result<()> {
    tokio::signal::ctrl_c().await?;
    handle.stop_graceful(None);
    Ok(())
}
